# -*- coding: utf-8 -*-
import logging

from datetime import datetime

import api.base
import utils.request
from aiohttp import ClientSession, CookieJar
import aiohttp
from typing import *

import shelve
import qrcode
import io
import base64
import config
from api.cookie_store import CookieStore
from api.refresh_cookie import BiliCookieRefresher
import blivedm.blivedm.clients.web as dm_web_cli

logger = logging.getLogger(__name__)


class StatusHandler(api.base.ApiHandler):  # noqa
    async def get(self):
        with shelve.open('data/login') as db:
            cookie = db.get('cookie')
            if not cookie:
                self.write({
                    'is_login': False,
                    'success': False,
                })
                return
            self.write({
                'is_login': True,
                'success': True,
                'login_date': db.get('date')
            })


class KillHandler(api.base.ApiHandler):  # noqa
    async def get(self):
        with shelve.open('data/login') as db:
            del db['cookie']
            del db['date']
        utils.request.reload_cookie()
        self.write({})


class StartHandler(api.base.ApiHandler):  # noqa
    async def get(self):
        async with ClientSession(headers={
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36'
        }) as session:
            res = await session.get('https://passport.bilibili.com/x/passport-login/web/qrcode/generate',
                                    params={'source': 'live_pc'})
            data = await res.json()
            login_url = data['data']['url']
            qrcode_key = data['data']['qrcode_key']

            qr = qrcode.QRCode(
                version=1,
                error_correction=qrcode.constants.ERROR_CORRECT_L,
                box_size=10,
                border=1,
            )
            qr.make(fit=True)
            qr.add_data(login_url)
            img = qr.make_image()

            byte_arr = io.BytesIO()
            img.save(byte_arr, format='PNG')

            # 原版
            # img = qrcode.make(login_url)
            # # Save the image to byte array
            # byte_arr = io.BytesIO()
            # img.save(byte_arr, format='PNG')

            byte_arr = byte_arr.getvalue()

            b64 = base64.b64encode(byte_arr)

            self.write({
                'qr': b64.decode('utf-8'),
                'key': qrcode_key
            })


class CheckHandler(api.base.ApiHandler):  # noqa
    async def get(self):
        async with ClientSession(headers={
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36'
        }) as session:
            qrcode_key = self.get_query_argument('qrcode_key')

            res = await session.get('https://passport.bilibili.com/x/passport-login/web/qrcode/poll',
                                    params={'qrcode_key': qrcode_key})
            data = await res.json()

            state = data['data']['code']
            refresh_token = data['data']['refresh_token']
            # print(refresh_token)
            if state == 0:
                # cookies = session.cookie_jar.filter_cookies('https://bilibili.com')
                cookies = res.cookies
                # print(cookies)
                with shelve.open('data/login') as db:
                    db['cookie'] = cookies
                    db['date'] = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
                    db['refresh_token'] = refresh_token
                utils.request.reload_cookie()
                self.write({
                    'ok': True,
                })
            else:
                self.write({
                    'ok': False,
                })


ROOM_INIT_URL = 'https://api.live.bilibili.com/xlive/web-room/v1/index/getInfoByRoom'
DANMAKU_SERVER_CONF_URL = 'https://api.live.bilibili.com/xlive/web-room/v1/index/getDanmuInfo'
# 获取用户信息
NAV = 'https://api.bilibili.com/x/web-interface/nav'

# todo 这里看看能不能改 不能改就不用了
class AuthHandler(api.base.ApiHandler):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self._user_agent = ''
        self._http_session: Optional[aiohttp.ClientSession] = None

    # noqa
    async def get(self):
        try:
            room_id = int(self.get_query_argument('room_id'))

            cookie = None
            with shelve.open('data/login') as db:
                cookie = db.get('cookie')

            async with ClientSession(headers={
                    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36'
                }) as session:
                self._http_session = session
                wbi_signer = dm_web_cli._get_wbi_signer(self._http_session)
                res = await session.get(
                    DANMAKU_SERVER_CONF_URL,
                    header = {
                        'Cookie': cookie
                    },
                    params = wbi_signer.add_wbi_sign({
                    'id': room_id,
                    'web_location':444.8,
                    'type': 0
                }))
                if res.status != 200:
                    logger.warning('room=%d getDanmuInfo() failed, status=%d, reason=%s', room_id,res.status, res.reason)
                    return
                data_json = await res.json()
                if data_json['code'] != 0:
                    logger.warning('room=%d getDanmuInfo() failed, message=%s', room_id,data_json['message'])
                    return

                data = data_json['data']
                token = data['token']

                if cookie is None:
                    self.write({
                        'uid': 0,
                        'roomid': room_id,
                        'protover': 3,
                        'platform': 'web',
                        'key': token
                    })
                    return
                else:
                    user_id = cookie['DedeUserID'].value
                    self.write({
                        'uid': int(user_id),
                        'roomid': room_id,
                        'protover': 3,
                        'platform': 'web',
                        'key': token,
                        'buvid': '',
                        'type': 2
                    })
                    return

        except Exception as ex:
            logger.exception(ex)
    async def _get_wbi_signer(self):
        # wbi_signer = dm_web_cli._get_wbi_signer(self._http_session)
        pass



# 检查是否需要刷新cookie
def check_refresh_cookie():
    # 从数据库中获取cookie和refresh_token
    (cookie_dict, refresh_token) = CookieStore.get_cookie_token()
    if not cookie_dict:
        return False
    # 创建刷新器实例
    refresher = BiliCookieRefresher(cookie_dict, refresh_token)
    # 执行刷新流程
    success = refresher.refresh_cookie()
    if success:
        print("Cookie刷新流程完成")
        print("新的Cookie:", refresher.get_current_cookie())
        print('simple_cookie', refresher.get_simple_cookie())
        print("新的refresh_token:", refresher.get_current_refresh_token())
        CookieStore.set_cookie_and_token(refresher.get_simple_cookie(),  refresher.get_current_refresh_token())
        return True
    else:
        print("Cookie刷新流程失败")
        return False

class RefreshCookieHandler(api.base.ApiHandler):
    async def get(self):
        try:
            result = check_refresh_cookie()
            self.write({
                'success': result,
                'message': 'Cookie刷新成功' if result else 'Cookie刷新失败',
                'login_date':datetime.now().strftime('%Y-%m-%d %H:%M:%S')
            })

        except Exception as ex:
            logger.exception(ex)
            self.write({
                'success': False,
                'message': f'刷新异常: {str(ex)}'
            })


ROUTES = [
    (r'/api/login/status', StatusHandler),
    (r'/api/login/start', StartHandler),
    (r'/api/login/check', CheckHandler),
    (r'/api/login/auth', AuthHandler),
    (r'/api/login/kill', KillHandler),
    (r'/api/refresh/cookie', RefreshCookieHandler),
]
